using Microsoft.VisualStudio.TestTools.UnitTesting;
using kratos;
using rpc;
using System.Net;
using System.Net.Sockets;
using System;
using System.Threading.Tasks;

namespace test_rpc
{
    [TestClass]
    public class UnitTest1
    {
        bool except = false;
        bool connected = false;
        int except_count = 0;
        ulong login_id = 0;
        async void DoTestConnect1()
        {
            connected = false;
            var rpc = RpcFactory.create();
            connected = await rpc.Connect("127.0.0.1", 45678, 500);
        }

        void Update(IRpc rpc, long timeout = 500)
        {
            var start = Util.GetNowMS();
            while (true)
            {
                rpc.Update();
                if (Util.GetNowMS() - start > timeout)
                {
                    break;
                }
            }
            rpc.Close();
        }

        [TestMethod]
        public void TestConnect1()
        {
            var rpc = RpcFactory.create();
            DoTestConnect1();
            Update(rpc);
            Assert.IsFalse(connected);
        }

        async void DoTestReconnect1()
        {
            connected = false;
            var rpc = RpcFactory.create();
            connected = await rpc.Reconnect();
        }

        [TestMethod]
        public void TestReconnect1()
        {
            var rpc = RpcFactory.create();
            DoTestReconnect1();
            Update(rpc);
            Assert.IsFalse(connected);
        }

        async void DoCallTimeout1()
        {
            connected = false;
            except = false;
            var rpc = RpcFactory.create();
            connected = await rpc.Connect("127.0.0.1", 4567, 200);
            var prx = Proxy.GetLogin();
            try
            {
                var id = await prx.login("123", "456", 200);
            }
            catch (RpcCallTimeoutException)
            {
                except = true;
            }
        }

        [TestMethod]
        public void TestCallTimeout1()
        {
            IPAddress Ip_addr = IPAddress.Parse("127.0.0.1");
            IPEndPoint end_point = new IPEndPoint(Ip_addr, 4567);
            TcpListener listener = new TcpListener(end_point);
            listener.Start();
            var rpc = RpcFactory.create();
            DoCallTimeout1();
            Socket sock = listener.AcceptSocket();
            Update(rpc, 1500);
            Assert.IsTrue(except);
            Assert.IsTrue(connected);
            listener.Stop();
        }

        async void DoCallTimeout2()
        {
            connected = false;
            except = false;
            except_count = 0;
            var rpc = RpcFactory.create();
            connected = await rpc.Connect("127.0.0.1", 10000, 200);
            var prx = Proxy.GetLogin();
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    var id = await prx.login("123", "456", 50);
                }
                catch (RpcCallTimeoutException)
                {
                    except = true;
                    except_count += 1;
                }
            }
        }

        [TestMethod]
        public void TestCallTimeout2()
        {
            IPAddress Ip_addr = IPAddress.Parse("127.0.0.1");
            IPEndPoint end_point = new IPEndPoint(Ip_addr, 10000);
            TcpListener listener = new TcpListener(end_point);
            listener.Start();
            var rpc = RpcFactory.create();
            DoCallTimeout2();
            Socket sock = listener.AcceptSocket();
            Update(rpc, 1500);
            Assert.IsTrue(except);
            Assert.IsTrue(connected);
            Assert.IsTrue(except_count == 10);
            listener.Stop();
        }

        async void DoCall1()
        {
            connected = false;
            except = false;
            except_count = 0;
            var rpc = RpcFactory.create();
            var prx = Proxy.GetLogin(true);
            login_id = await prx.login("123", "456", 50);
        }

        [TestMethod]
        public void TestCall1()
        {
            DoCall1();
            Assert.IsTrue(login_id == 1);
        }

        async void DoCall2()
        {
            login_id = 0;
            connected = false;
            except = false;
            except_count = 0;
            var rpc = RpcFactory.create();
            var prx = Proxy.GetLogin(true);
            await prx.login("123", "456", 50);
            login_id = await prx.login("123", "456", 50);
        }

        [TestMethod]
        public void TestCall2()
        {
            DoCall2();
            Assert.IsTrue(login_id == 1);
        }
    }
}
